# device_manager.py
import subprocess, threading, time
from datetime import datetime
from xhs.task_worker import DeviceWorker
from xhs import config
from xhs.ui import DeviceManagerUI
from xhs.ui_signal import ui_signal
from xhs.my_log import log
from xhs.db_queue import data_device_load, data_device_add, data_device_load_open
from xhs import xhs_service

base_connect_type = "none"


class DeviceManager:
    def __init__(self, ui: DeviceManagerUI):
        # 全局维护设备状态：device_id -> dict(status, thread, last_seen)
        self.device_map = {}
        self.lock = threading.Lock()
        self.ui = ui

    def on_worker_exit(self, device_id):
        # 设备线程退出后清理记录
        with self.lock:
            if device_id in self.device_map:
                del self.device_map[device_id]
                log(f"[{device_id}] 清理线程")

    def adb_devices_detail(self, connect_type="all"):
        """
        获取ADB连接的设备详情，可选择仅获取 USB / WiFi 连接的设备。
        """
        assert connect_type in ("usb", "wifi", "all"), "您还未开启设备扫描"

        result = subprocess.run(["adb", "devices"], capture_output=True, text=True)
        lines = result.stdout.strip().splitlines()[1:]

        device_info_list = []

        for line in lines:
            if "device" not in line or "offline" in line:
                continue

            device_id = line.split()[0]

            # 判断连接类型（根据 device_id 是否为 IP）
            is_wifi = ":" in device_id and device_id[0].isdigit()
            is_usb = not is_wifi

            if connect_type == "usb" and not is_usb:
                continue
            if connect_type == "wifi" and not is_wifi:
                continue

            def get_prop(prop):
                return subprocess.getoutput(f"adb -s {device_id} shell getprop {prop}").strip()

            info = {
                "device_id": device_id,
                "brand": get_prop("ro.product.brand"),
                "model": get_prop("ro.product.model"),
                "version": get_prop("ro.build.version.release"),
                "device_name": get_prop("persist.sys.device_name"),
                "app": "1"
            }
            device_info_list.append(info)

        return device_info_list

    def scan_loop(self):
        """
        循环扫描 ADB 在线设备，动态管理线程（使用详细设备信息）
        """
        current_device_ids = []
        while True:
            try:
                # 获取在线的全部设备
                devices_info = self.adb_devices_detail(base_connect_type)
                now = datetime.utcnow()
                current_device_ids = [dev["device_id"] for dev in devices_info]
                log(f"扫描设备,间隔{config.device_scan_sleep}秒,{current_device_ids}")

                # === 修改点: 从数据库加载已知设备状态 ===
                db_devices = data_device_load()  # 加载全部设备数据
                db_device_map = {d["device_id"]: d for d in db_devices}  # 映射为 device_id -> 设备 dict

                with self.lock:
                    # 更新 self.device_map = 仅包含已开启并在线的设备
                    self.device_map_open = {
                        device_id: self.device_map.get(device_id, {})  # 保留原有线程等结构
                        for device_id in db_device_map
                        if db_device_map[device_id].get("open_status") == "开启" and device_id in current_device_ids
                    }
                    # 如果数据库查询状态是关闭的话，则不放入线程中

                    # 处理新上线设备（只要ADB能扫到）
                    for dev in devices_info:
                        device_id = dev["device_id"]

                        if device_id not in db_device_map:
                            # === 新设备：添加到数据库 ===
                            dev["open_status"] = "关闭"
                            dev["app"] = "1"
                            data_device_add(dev)
                            log(f"[{device_id}] 首次发现设备: {dev['brand']} {dev['model']} Android {dev['version']}")
                            continue  # 默认关闭不启动线程

                        # 关闭的数据清理掉
                        if db_device_map[device_id].get("open_status") != "开启":
                            if device_id in self.device_map:
                                current_device_ids.remove(device_id)
                            continue  # 跳过未开启的设备

                        if device_id not in self.device_map:
                            log(f"[{device_id}] 上线并开启: {dev['brand']} {dev['model']} Android {dev['version']}")

                            worker = DeviceWorker(db_device_map[device_id], self.on_worker_exit)
                            t = threading.Thread(target=worker.run, daemon=True)
                            self.device_map[device_id] = {
                                "status": "online",
                                "thread": t,
                                "worker": worker,
                                "last_seen": now,
                                "info": dev
                            }
                            t.start()
                        else:
                            # 更新已存在的在线设备信息
                            self.device_map[device_id]["status"] = "online"
                            self.device_map[device_id]["last_seen"] = now
                            self.device_map[device_id]["info"] = dev

                        #扫描一次设备异常则报警
                        xhs_service.un_read(self.device_map)


                    # 检查掉线设备
                    for device_id in list(self.device_map.keys()):
                        if device_id not in current_device_ids:
                            info = self.device_map[device_id]
                            if info["status"] != "offline":
                                ui_signal.set_log.emit(f"[{device_id}] 掉线设备")
                                info["status"] = "offline"
                                info["worker"].stop()

            except Exception as e:
                log(f"[设备扫描异常] {e}")
                devices_info = []

            # 每次扫描完查询最新数据库
            db_device_data = data_device_load()

            devices_info = []
            for db_device in db_device_data:
                if db_device["device_id"] in current_device_ids:
                    db_device["status"] = "在线"
                else:
                    db_device["status"] = "离线"

            ui_signal.set_devices_signal.emit(db_device_data)
            time.sleep(config.device_scan_sleep)

# 1保留源代码格式别动，包括注释日志等
# 2device_map的数据改为从数据方法data_device_load查询出来的
# 3如果上线新设备，数据库中没有则新增data_device_add，默认是不开启的
# 4 数据库表结构如下{
#     "device_name": "001",
#     "device_id": "asdjkashj22",
#     "brand": "Xiaomi",
#     "model": "Mi 11",
#     "version": "12.5",
#     "device_name": "设备一号",
#     "status": "开启"
#   }
#
